فارسی

قدرت فدراسیون GraphQL را با الصاق اسکما آزاد کنید. بیاموزید چگونه یک API GraphQL یکپارچه از چندین سرویس بسازید و مقیاس‌پذیری و قابلیت نگهداری را بهبود بخشید.

فدراسیون GraphQL: الصاق اسکما (Schema Stitching) - یک راهنمای جامع

در چشم‌انداز همواره در حال تحول توسعه اپلیکیشن‌های مدرن، نیاز به معماری‌های مقیاس‌پذیر و قابل نگهداری به امری حیاتی تبدیل شده است. میکروسرویس‌ها، با ماهیت ماژولار و قابلیت استقرار مستقل خود، به عنوان یک راه‌حل محبوب مطرح شده‌اند. با این حال، مدیریت تعداد زیادی میکروسرویس می‌تواند پیچیدگی‌هایی را به همراه داشته باشد، به ویژه زمانی که صحبت از ارائه یک API یکپارچه به اپلیکیشن‌های کلاینت می‌شود. اینجاست که فدراسیون GraphQL و به طور خاص، الصاق اسکما (Schema Stitching)، وارد عمل می‌شود.

فدراسیون GraphQL چیست؟

فدراسیون GraphQL یک معماری قدرتمند است که به شما امکان می‌دهد یک API GraphQL واحد و یکپارچه از چندین سرویس GraphQL زیربنایی (که اغلب نماینده میکروسرویس‌ها هستند) بسازید. این معماری به توسعه‌دهندگان اجازه می‌دهد تا داده‌ها را در سرویس‌های مختلف به گونه‌ای کوئری کنند که گویی یک گراف واحد هستند، که این امر تجربه کلاینت را ساده کرده و نیاز به منطق پیچیده هماهنگی در سمت کلاینت را کاهش می‌دهد.

دو رویکرد اصلی برای فدراسیون GraphQL وجود دارد:

این مقاله بر روی الصاق اسکما (Schema Stitching) تمرکز دارد و مفاهیم، مزایا، محدودیت‌ها و پیاده‌سازی عملی آن را بررسی می‌کند.

درک مفهوم الصاق اسکما (Schema Stitching)

الصاق اسکما فرآیند ادغام چندین اسکما GraphQL در یک اسکما واحد و منسجم است. این اسکما یکپارچه به عنوان یک نما (facade) عمل می‌کند و پیچیدگی سرویس‌های زیربنایی را از دید کلاینت پنهان می‌سازد. هنگامی که یک کلاینت درخواستی را به اسکما الصاق شده ارسال می‌کند، gateway به طور هوشمندانه درخواست را به سرویس یا سرویس‌های زیربنایی مناسب هدایت می‌کند، داده‌ها را بازیابی کرده و نتایج را قبل از بازگرداندن به کلاینت ترکیب می‌کند.

این فرآیند را اینگونه تصور کنید: شما چندین رستوران (سرویس) دارید که هر کدام در غذاهای مختلف تخصص دارند. الصاق اسکما مانند یک منوی جهانی است که تمام غذاهای هر رستوران را ترکیب می‌کند. هنگامی که یک مشتری (کلاینت) از منوی جهانی سفارش می‌دهد، سفارش به طور هوشمندانه به آشپزخانه‌های رستوران مناسب هدایت می‌شود، غذا آماده شده و سپس در یک تحویل واحد برای مشتری ترکیب می‌شود.

مفاهیم کلیدی در الصاق اسکما

مزایای الصاق اسکما

الصاق اسکما مزایای قانع‌کننده‌ای را برای سازمان‌هایی که از معماری میکروسرویس استفاده می‌کنند، ارائه می‌دهد:

محدودیت‌های الصاق اسکما

در حالی که الصاق اسکما مزایای زیادی دارد، آگاهی از محدودیت‌های آن مهم است:

پیاده‌سازی عملی الصاق اسکما

بیایید یک مثال ساده از نحوه پیاده‌سازی الصاق اسکما با استفاده از Node.js و کتابخانه graphql-tools (یک انتخاب محبوب برای الصاق اسکما) را مرور کنیم. این مثال شامل دو میکروسرویس است: یک سرویس کاربر (User Service) و یک سرویس محصول (Product Service).

1. تعریف اسکماهای راه دور

ابتدا، اسکماهای GraphQL را برای هر یک از سرویس‌های راه دور تعریف کنید.

سرویس کاربر (user-service.js):


const { buildSchema } = require('graphql');

const userSchema = buildSchema(`
  type User {
    id: ID!
    name: String
    email: String
  }

  type Query {
    user(id: ID!): User
  }
`);

const users = [
  { id: '1', name: 'Alice Smith', email: 'alice@example.com' },
  { id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];

const userRoot = {
  user: (args) => users.find(user => user.id === args.id),
};

module.exports = {
  schema: userSchema,
  rootValue: userRoot,
};

سرویس محصول (product-service.js):


const { buildSchema } = require('graphql');

const productSchema = buildSchema(`
  type Product {
    id: ID!
    name: String
    price: Float
    userId: ID!  # کلید خارجی به سرویس کاربر
  }

  type Query {
    product(id: ID!): Product
  }
`);

const products = [
  { id: '101', name: 'Laptop', price: 1200, userId: '1' },
  { id: '102', name: 'Smartphone', price: 800, userId: '2' },
];

const productRoot = {
  product: (args) => products.find(product => product.id === args.id),
};

module.exports = {
  schema: productSchema,
  rootValue: productRoot,
};

2. ایجاد سرویس Gateway

اکنون، سرویس gateway را ایجاد کنید که دو اسکما را به هم الصاق می‌کند.

سرویس Gateway (gateway.js):


const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');

async function createRemoteSchema(uri) {
  const fetcher = async (params) => {
    const response = await fetch(uri, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(params),
    });
    return response.json();
  };

  const schema = await introspectSchema(fetcher);
  return makeRemoteExecutableSchema({
    schema,
    fetcher,
  });
}

async function main() {
  const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
  const productSchema = await createRemoteSchema('http://localhost:4002/graphql');

  const stitchedSchema = stitchSchemas({
    subschemas: [
      { schema: userSchema },
      { schema: productSchema },
    ],
    typeDefs: `
      extend type Product {
        user: User
      }
    `,
    resolvers: {
      Product: {
        user: {
          selectionSet: `{ userId }`,
          resolve(product, args, context, info) {
            return info.mergeInfo.delegateToSchema({
              schema: userSchema,
              operation: 'query',
              fieldName: 'user',
              args: {
                id: product.userId,
              },
              context,
              info,
            });
          },
        },
      },
    },
  });

  const app = express();
  app.use('/graphql', graphqlHTTP({
    schema: stitchedSchema,
    graphiql: true,
  }));

  app.listen(4000, () => console.log('سرور Gateway در آدرس http://localhost:4000/graphql در حال اجراست'));
}

main().catch(console.error);

3. اجرای سرویس‌ها

شما باید سرویس کاربر و سرویس محصول را روی پورت‌های مختلف اجرا کنید. به عنوان مثال:

سرویس کاربر (پورت 4001):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4001, () => console.log('سرویس کاربر در آدرس http://localhost:4001/graphql در حال اجراست'));

سرویس محصول (پورت 4002):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4002, () => console.log('سرویس محصول در آدرس http://localhost:4002/graphql در حال اجراست'));

4. کوئری زدن به اسکما الصاق شده

اکنون می‌توانید از طریق gateway (که روی پورت 4000 در حال اجراست) به اسکما الصاق شده کوئری بزنید. می‌توانید کوئری مانند این را اجرا کنید:


query {
  product(id: "101") {
    id
    name
    price
    user {
      id
      name
      email
    }
  }
}

این کوئری محصول با شناسه "101" را بازیابی می‌کند و همچنین کاربر مرتبط را از سرویس کاربر دریافت می‌کند، که نشان می‌دهد چگونه الصاق اسکما به شما امکان می‌دهد داده‌ها را در چندین سرویس در یک درخواست واحد کوئری کنید.

تکنیک‌های پیشرفته الصاق اسکما

فراتر از مثال پایه، در اینجا چند تکنیک پیشرفته وجود دارد که می‌توان برای بهبود پیاده‌سازی الصاق اسکما استفاده کرد:

انتخاب بین الصاق اسکما و فدراسیون آپولو

در حالی که الصاق اسکما یک گزینه مناسب برای فدراسیون GraphQL است، فدراسیون آپولو به دلیل ویژگی‌های پیشرفته و تجربه توسعه‌دهنده بهبود یافته، به انتخاب محبوب‌تری تبدیل شده است. در اینجا مقایسه‌ای بین این دو رویکرد آورده شده است:

ویژگی الصاق اسکما فدراسیون آپولو
تعریف اسکما از زبان اسکما GraphQL موجود استفاده می‌کند از یک زبان اسکما اعلانی با دایرکتیوها استفاده می‌کند
برنامه‌ریزی کوئری نیازمند تفویض کوئری دستی است برنامه‌ریزی خودکار کوئری توسط Apollo Gateway
افزونه‌های نوع پشتیبانی محدود پشتیبانی داخلی برای افزونه‌های نوع
دایرکتیوهای کلید پشتیبانی نمی‌شود از @key directive برای شناسایی موجودیت‌ها استفاده می‌کند
ردیابی توزیع‌شده نیازمند پیاده‌سازی دستی است پشتیبانی داخلی برای ردیابی توزیع‌شده
ابزارها و اکوسیستم ابزارهای کمتر بالغ ابزارهای بالغ‌تر و یک جامعه بزرگ
پیچیدگی مدیریت آن در سیستم‌های بزرگ می‌تواند پیچیده باشد برای سیستم‌های بزرگ و پیچیده طراحی شده است

چه زمانی الصاق اسکما را انتخاب کنیم:

چه زمانی فدراسیون آپولو را انتخاب کنیم:

نمونه‌های واقعی و موارد استفاده

در اینجا چند نمونه واقعی از نحوه استفاده از فدراسیون GraphQL، از جمله الصاق اسکما، آورده شده است:

بهترین شیوه‌ها برای الصاق اسکما

برای اطمینان از پیاده‌سازی موفق الصاق اسکما، این بهترین شیوه‌ها را دنبال کنید:

نتیجه‌گیری

فدراسیون GraphQL با الصاق اسکما یک رویکرد قدرتمند برای ساخت APIهای یکپارچه از چندین سرویس در معماری میکروسرویس ارائه می‌دهد. با درک مفاهیم اصلی، مزایا، محدودیت‌ها و تکنیک‌های پیاده‌سازی آن، می‌توانید از الصاق اسکما برای ساده‌سازی دسترسی به داده‌ها، بهبود مقیاس‌پذیری و افزایش قابلیت نگهداری استفاده کنید. در حالی که فدراسیون آپولو به عنوان یک راه‌حل پیشرفته‌تر ظهور کرده است، الصاق اسکما همچنان یک گزینه مناسب برای سناریوهای ساده‌تر یا هنگام یکپارچه‌سازی سرویس‌های GraphQL موجود باقی می‌ماند. نیازها و الزامات خاص خود را با دقت در نظر بگیرید تا بهترین رویکرد را برای سازمان خود انتخاب کنید.